package com.block.match.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.enums.InfoTypeEnum;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.model.vo.ResultInfoVO;
import com.block.common.service.IApplicationInfoService;
import com.block.common.service.LogFactory;
import com.block.common.service.impl.ChannelCommonService;
import com.block.common.service.merchant.IMerchantThirdBaseInfoService;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.*;
import com.block.db.mapper.*;
import com.block.match.enums.OrderStatusEnum;
import com.block.match.service.IDataMatchOrderItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.merchant.model.result.DataPushResult;
import com.block.merchant.model.result.MatchMerchantInfo;
import com.block.merchant.service.IDataMerchantPushService;
import com.block.merchant.service.IMerchantBaseInfoService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 商户匹配订单子项信息 服务实现类
 * </p>
 *
 * @author 
 * @since 2023-08-15
 */
@Service
public class DataMatchOrderItemServiceImpl extends ServiceImpl<DataMatchOrderItemMapper, DataMatchOrderItem> implements IDataMatchOrderItemService {

    private static final Logger log = LogFactory.getMerchantLog();

    @Autowired
    IDataMerchantPushService dataMerchantPushService;
    @Autowired
    IMerchantBaseInfoService merchantBaseInfoService;

    @Autowired
    IMerchantThirdBaseInfoService merchantThirdBaseInfoService;
    @Resource
    MerchantThirdBaseInfoMapper merchantThirdBaseInfoMapper;
    @Resource
    MerchantBaseInfoMapper merchantBaseInfoMapper;
    @Autowired
    ChannelCommonService channelCommonService;
    @Autowired
    IApplicationInfoService applicationInfoService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Resource
    MerchantThirdProtocolInfoMapper merchantThirdProtocolInfoMapper;
    @Autowired
    NotifyExceptionService notifyExceptionService;
    @Resource
    MerchantDataPushJobMapper merchantDataPushJobMapper;

    @Override
    public DataMatchOrderItem initMatchOrderItem(MatchMerchantInfo matchMerchantInfo, DataMatchOrderInfo dataMatchOrderInfo, MemberSourceInfo memberSourceInfo) {

        DataMatchOrderItem matchOrderItem = new DataMatchOrderItem();
        matchOrderItem.setOrderId(dataMatchOrderInfo.getId());
        matchOrderItem.setDateInfo(LocalDate.now().toString());
        matchOrderItem.setInfoId(matchMerchantInfo.getInfoId());
        matchOrderItem.setInfoType(matchMerchantInfo.getInfoType());
        matchOrderItem.setUid(memberSourceInfo.getUid());
        matchOrderItem.setTaskId(matchMerchantInfo.getTaskId());
        matchOrderItem.setProfitAmount(matchMerchantInfo.getProfitAmount());
        matchOrderItem.setAppCode(memberSourceInfo.getAppCode());
        matchOrderItem.setAppName(memberSourceInfo.getAppName());
        matchOrderItem.setChannelCode(memberSourceInfo.getChannelCode());
        matchOrderItem.setChannelName(memberSourceInfo.getChannelName());
        matchOrderItem.setPushId(matchMerchantInfo.getPushId());

        matchOrderItem.setApproveUrl(matchMerchantInfo.getApproveUrl());
        matchOrderItem.setApproveFlag(matchMerchantInfo.getApproveFlag());
        matchOrderItem.setProtocolUrl(matchMerchantInfo.getProtocolUrl());

        if (StrUtil.equals(matchMerchantInfo.getInfoType(), "APIB") && StrUtil.isEmpty(matchMerchantInfo.getApproveUrl())){
            // 判断跳转地址是否为空
            matchOrderItem.setStatus(OrderStatusEnum.INIT.getValue());
        }else{
            // CRM 或者 API 直接设置为待推送
            matchOrderItem.setStatus(OrderStatusEnum.WAIT_PUSH.getValue());
        }

        matchOrderItem.setApproveFlag(matchMerchantInfo.getApproveFlag());
        matchOrderItem.setApproveUrl(matchMerchantInfo.getApproveUrl());
        matchOrderItem.setProtocolUrl(matchMerchantInfo.getProtocolUrl());// 机构的协议地址

        boolean save = this.save(matchOrderItem);

        if (save){
            return this.getById(matchOrderItem.getId());
        }
        return null;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public DataMatchOrderItem toPushItemOrder(String orderId, String itemOrderId) throws Exception {

        DataMatchOrderItem dataMatchOrderItem = this.baseMapper.getEntityByItemOrderIdLock(itemOrderId);
        //如果是大象，返回null
        if (dataMatchOrderItem.getInfoId() == 380 && StrUtil.equals(dataMatchOrderItem.getInfoType(), "API")){
            // 同一个机构和渠道，相同的uid ，6个小时内只能待进件入库一次
            String infoId = String.valueOf(dataMatchOrderItem.getInfoId());
            String  uid = String.valueOf(dataMatchOrderItem.getUid());
            String channelCode = dataMatchOrderItem.getChannelCode();
            String redisKey = StrUtil.format(RedisKeyConstant.XXLJOB_DAXIANG_REGISTER_CHANNEL, infoId, channelCode, uid);
            // 查询缓存是否有
            boolean setIfAbsent = stringRedisTemplate.opsForValue().setIfAbsent(redisKey, "0", 6, TimeUnit.HOURS);
            if (!setIfAbsent){
                // 6小时之内不能重复待进件入库lq_merchant_data_push_job
                return null;
            }
            /**
             * 将传入的信息存入库中
             * id，info_id，info_name，info_type，uid，order_id，order_item_id，create_date，update_date，status
             * */
            MerchantDataPushJob merchantDataPushJob = new MerchantDataPushJob();
            merchantDataPushJob .setInfoId(dataMatchOrderItem.getInfoId());
            merchantDataPushJob .setInfoType(dataMatchOrderItem.getInfoType());
            merchantDataPushJob .setUid(dataMatchOrderItem.getUid());
            merchantDataPushJob .setOrderId(dataMatchOrderItem.getOrderId());
            merchantDataPushJob .setOrderItemId(Long.valueOf(itemOrderId));
            MerchantBaseInfo merchantBaseInfo = merchantBaseInfoMapper.selectById(dataMatchOrderItem.getInfoId());
            merchantDataPushJob.setInfoName(merchantBaseInfo.getInfoName());
            merchantDataPushJobMapper.insert(merchantDataPushJob);
            return null;
        }


        if (StrUtil.equals(dataMatchOrderItem.getInfoType(), "APIB")){
            // 入股是apiB 类型的用户，不在这里进行操作
            // 状态设置为待确认
            DataMatchOrderItem updateEntity = new DataMatchOrderItem();
            updateEntity.setId(Long.valueOf(itemOrderId));
            updateEntity.setClickPushFlag(1);
            updateEntity.setStatus(OrderStatusEnum.WAIT_CONFIRM.getValue());
            updateEntity.setRemarkInfo("APPROVE_PAGE");

            this.updateById(updateEntity);
            return null;
        }
        // 订单进行推送
        DataPushResult dataPushResult = merchantBaseInfoService.pushToMerchant(dataMatchOrderItem);

        DataMatchOrderItem updateEntity = new DataMatchOrderItem();
        updateEntity.setId(Long.valueOf(itemOrderId));
        updateEntity.setClickPushFlag(1);

        if (ObjectUtil.isNotEmpty(dataPushResult.getPushOrderId())){
            updateEntity.setPushId(String.valueOf(dataPushResult.getPushOrderId()));
        }

        if (dataPushResult.isPushSuccess()){
            updateEntity.setStatus(OrderStatusEnum.SUCCESS.getValue());
        }else{
            updateEntity.setStatus(OrderStatusEnum.FAILED.getValue());
        }
        this.updateById(updateEntity);

        return dataMatchOrderItem;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public DataMatchOrderItem pushApiB(String orderId, String itemOrderId) throws Exception {
        DataMatchOrderItem dataMatchOrderItem = this.baseMapper.getEntityByItemOrderIdLock(itemOrderId);

        // 订单进行推送
        DataPushResult dataPushResult = merchantBaseInfoService.pushToMerchant(dataMatchOrderItem);

        DataMatchOrderItem updateEntity = new DataMatchOrderItem();
        updateEntity.setId(Long.valueOf(itemOrderId));
        updateEntity.setClickPushFlag(1);

        if (ObjectUtil.isNotEmpty(dataPushResult.getPushOrderId())){
            updateEntity.setPushId(String.valueOf(dataPushResult.getPushOrderId()));
        }

        if (dataPushResult.isPushSuccess()){
            updateEntity.setStatus(OrderStatusEnum.SUCCESS.getValue());
        }else{
            updateEntity.setStatus(OrderStatusEnum.FAILED.getValue());
        }
        this.updateById(updateEntity);

        return dataMatchOrderItem;
    }

    /**
     * 查询最后成功的一条数据
     *
     */
    @Override
    public JSONObject getLastedSuccessPushProduct(Long uid){

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("hasPushMsg", 0);

        if (!ObjectUtil.equals(uid, 0L)){
            // 查询最新申请成功的机构信息
            String dateInfo = LocalDate.now().minusDays(7L).toString();
            // 查询近7天
            DataMatchOrderItem matchOrderItem = this.baseMapper.getLastedSuccessEntityByUid(uid, dateInfo);

            try {
                if (ObjectUtil.isNotEmpty(matchOrderItem)){
                    JSONObject pushInfoObject = getInfoByOrderItem(matchOrderItem);
                    jsonObject.put("pushProductInfo", pushInfoObject);

                    jsonObject.put("hasPushMsg", 1);

                }
            }catch (Exception exception){
               exception.printStackTrace();
               notifyExceptionService.notifyNoticeInfo("MAIN_SUCCESS_ORDER", "首页订单查询异常", uid+"", exception);
            }
        }
        return jsonObject;
    }

    /**
     * 查询用户的申请列表
     * @param uid
     * @return
     */
    @Override
    public ResponseVo getOrderSuccessList(Long uid){

        List<JSONObject> orderList = new ArrayList<>();

        String dateInfo = LocalDate.now().minusDays(30L).toString();
        List<DataMatchOrderItem> matchOrderItemList = this.baseMapper.getOrderSuccessList(uid,dateInfo);
        for (DataMatchOrderItem matchOrderItem : matchOrderItemList) {

            try {
                JSONObject infoByOrderItem = this.getInfoByOrderItem(matchOrderItem);
                orderList.add(infoByOrderItem);
            }catch (Exception exception){
                exception.printStackTrace();
                notifyExceptionService.notifyNoticeInfo("SUCCESS_ORDER_LIST", "成功订单列表查询", uid+"", exception);
            }
        }

        JSONObject resultObject = new JSONObject();
        resultObject.put("dataList", orderList);

        return new ResponseVo(AppRspCodeConstant.SUCCESS, resultObject);
    }

    public JSONObject getInfoByOrderItem(DataMatchOrderItem matchOrderItem){

        JSONObject pushInfoObject = new JSONObject();

        if (StrUtil.equals(matchOrderItem.getInfoType(), InfoTypeEnum.APIS.getValue()) ){

            MerchantThirdBaseInfo thirdBaseInfo = merchantThirdBaseInfoMapper.selectEntityByOrderNo(matchOrderItem.getPushId());
            // 下游是 非 apis 类型
            pushInfoObject.put("companyName", thirdBaseInfo.getCompanyName());
            String companyLogo = thirdBaseInfo.getCompanyLogo();
            if (StringUtils.isEmpty(companyLogo)){
                pushInfoObject.put("logo", "");
            }else {
                pushInfoObject.put("logo", companyLogo);
            }

            pushInfoObject.put("productName", thirdBaseInfo.getProductName());
            pushInfoObject.put("productId", thirdBaseInfo.getProductId());

            pushInfoObject.put("successTime", LocalDateTimeUtil.format(matchOrderItem.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));

            List<MerchantThirdProtocolInfo> thirdProtocolInfoList = merchantThirdProtocolInfoMapper.selectListByThirdId(thirdBaseInfo.getId());
            JSONArray jsonArray =new JSONArray();
            //协议地址
            for (MerchantThirdProtocolInfo protocolInfo : thirdProtocolInfoList) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("protocolName",protocolInfo.getProtocolName());
                jsonObject.put("protocolUrl", protocolInfo.getProtocolUrl());
                jsonArray.add(jsonObject);
            }
            pushInfoObject.put("protocolList", jsonArray);

        }else{

            MerchantBaseInfo merchantBaseInfo = merchantBaseInfoMapper.selectById(matchOrderItem.getInfoId());
            // 下游是 非 apis 类型
            pushInfoObject.put("companyName", merchantBaseInfo.getCompanyName());
            String companyLogo = merchantBaseInfo.getCompanyLogo();
            if (StringUtils.isEmpty(companyLogo)){
                pushInfoObject.put("logo", "");
            }else {
                pushInfoObject.put("logo", merchantBaseInfo.getCompanyLogo());
            }

            pushInfoObject.put("productName", merchantBaseInfo.getInfoName());
            pushInfoObject.put("productId", merchantBaseInfo.getId());

            pushInfoObject.put("successTime", LocalDateTimeUtil.format(matchOrderItem.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));
            //协议地址

            JSONObject jsonObject = new JSONObject();
            ChannelBaseInfo baseInfoByCode = channelCommonService.getBaseInfoByCode(matchOrderItem.getChannelCode());
            ApplicationInfo appInfoByAppCode = applicationInfoService.getAppInfoByAppCode(baseInfoByCode.getAppCode());
            String protocolUrl = StrUtil.format("{}/page/newprotocol/{}/{}.html", appInfoByAppCode.getApiUrl(), matchOrderItem.getOrderId(), matchOrderItem.getOrderId());
            jsonObject.put("protocolName","授权协议");
            jsonObject.put("protocolUrl", protocolUrl);

            JSONArray jsonArray =new JSONArray();
            jsonArray.add(jsonObject);

            pushInfoObject.put("protocolList", jsonArray);
        }


        return pushInfoObject;
    }


}
